﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Principal;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Web;
using System.Linq;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OAuth;
using ezCloud.Api.Models;
using ezCloud.Api.Providers;
using ezCloud.Api.Results;
using ezCloud.Data;
using System.Data.Linq;
using CodeSmith.Data.Linq;
using System.Collections;

namespace ezCloud.Api.Common
{
    public class UserUtitily : ezController
    {
        //private static ApplicationUserManager _userManager;
        public static bool isAuthenticated()
        {
            return HttpContext.Current.User.Identity.IsAuthenticated;
        }
        public static List<AspNetUsers> getHotelUsers(ezCloudDataContext context, int hotelId)
        {
            var memcache = new Common.MemoryCacher();
            var hotelUsers = memcache.GetValue("HOTEL_USERS_" + hotelId);
            if (hotelUsers != null)
            {
                return (List<AspNetUsers>)hotelUsers;
            } else
            {
                var hotelOwner = context.Hotels.Where(ho => ho.HotelId == hotelId).FirstOrDefault();
                
                var allUsers = context.AspNetUsers.Where(u => u.DefaultHotelId == hotelId || u.Id == hotelOwner.HotelOwnerId).ToList();
                return allUsers;
            }
        }
        public static List<KeyValuePair<string, DateTime>> getOnlineUsers()
        {
            return ApiAuthorize.onlineUsers.Where(u => u.Value >= DateTime.UtcNow.AddMinutes(-15)).ToList();
        }
        public static void removeUserProfileCache(string userName)
        {
            var cache = new MemoryCacher();
            cache.Delete("USER_PROFILE_" + userName);
        }
        public static UserProfile getUserProfileById(string id)
        {
            ezCloudDataContext context = new ezCloudDataContext();
            var up = new UserProfile();
            
            ApplicationUserManager _userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
            var user = _userManager.FindById(id);
            up.UserName = user.UserName;
            up.HotelId = user.DefaultHotelId;
            up.UserId = user.Id;
            up.FullName = user.UserName;


            var isOwner = _userManager.IsInRole(user.Id, "ROLE_HOTEL_OWNER");
            if (isOwner)
            {
                up.Email = user.Email;
                var hotelOwnerProfile = context.HotelOwners.Where(ho => ho.UserId == up.UserId).FutureCacheFirstOrDefault(3600);
                if (hotelOwnerProfile != null && hotelOwnerProfile.IsLoaded && hotelOwnerProfile.Value != null)
                    up.FullName = hotelOwnerProfile.Value.FullName;

            }
            else
            {
                var staffProfile = context.Staffs.Where(st => st.UserId == up.UserId).FutureCacheFirstOrDefault(3600);
                if (staffProfile != null && staffProfile.IsLoaded && staffProfile.Value != null)
                {
                    up.FullName = staffProfile.Value.StaffName;
                    up.Email = staffProfile.Value.Email;
                }
            }            
            return up;

        }
        public static UserProfile getUserProfile()
        {
            ezCloudDataContext context = new ezCloudDataContext();
            var up = new UserProfile();
            if (!HttpContext.Current.User.Identity.IsAuthenticated)
                return up;
            var cache = new MemoryCacher();
            var cacheUP = cache.GetValue("USER_PROFILE_" + HttpContext.Current.User.Identity.GetUserName());
            if (cacheUP != null)
                return (UserProfile)cacheUP;
            //var username = HttpContext.Current.User.Identity.GetUserName().Split('@');
            //up.Username = username[0];
            up.UserName = HttpContext.Current.User.Identity.GetUserName();
            ApplicationUserManager _userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
            var user = _userManager.FindByName(up.UserName);
            up.HotelId = user.DefaultHotelId;
            up.UserId = user.Id;
            up.FullName = user.UserName;

           
            var isOwner = _userManager.IsInRole(user.Id, "ROLE_HOTEL_OWNER");
            if (isOwner) {
                up.Email = user.Email;
                var hotelOwnerProfile = context.HotelOwners.Where(ho => ho.UserId == up.UserId).FutureCacheFirstOrDefault(3600);
                if (hotelOwnerProfile!=null && hotelOwnerProfile.IsLoaded && hotelOwnerProfile.Value != null)
                    up.FullName = hotelOwnerProfile.Value.FullName;
                
            } else
            {
                var staffProfile = context.Staffs.Where(st => st.UserId == up.UserId).FutureCacheFirstOrDefault(3600);
                if (staffProfile != null && staffProfile.IsLoaded && staffProfile.Value != null)
                {
                    up.FullName = staffProfile.Value.StaffName;
                    up.Email = staffProfile.Value.Email;
                }
            }

            //var request = HttpContext.Current.Request;
            //up.HotelId = request.Headers["WorkingHotelId"] != null ? int.Parse(request.Headers["WorkingHotelId"]) : user.DefaultHotelId;
            cache.Add("USER_PROFILE_" + up.UserName, up, DateTimeOffset.UtcNow.AddHours(1));
            return up;
        }


        private class ExternalLoginData
        {
            public string LoginProvider { get; set; }
            public string ProviderKey { get; set; }
            public string UserName { get; set; }

            public IList<Claim> GetClaims()
            {
                IList<Claim> claims = new List<Claim>();
                claims.Add(new Claim(ClaimTypes.NameIdentifier, ProviderKey, null, LoginProvider));

                if (UserName != null)
                {
                    claims.Add(new Claim(ClaimTypes.Name, UserName, null, LoginProvider));
                }

                return claims;
            }

            public static ExternalLoginData FromIdentity(ClaimsIdentity identity)
            {
                if (identity == null)
                {
                    return null;
                }

                Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier);

                if (providerKeyClaim == null || String.IsNullOrEmpty(providerKeyClaim.Issuer)
                    || String.IsNullOrEmpty(providerKeyClaim.Value))
                {
                    return null;
                }

                if (providerKeyClaim.Issuer == ClaimsIdentity.DefaultIssuer)
                {
                    return null;
                }

                return new ExternalLoginData
                {
                    LoginProvider = providerKeyClaim.Issuer,
                    ProviderKey = providerKeyClaim.Value,
                    UserName = identity.FindFirstValue(ClaimTypes.Name)
                };
            }
        }

        private static class RandomOAuthStateGenerator
        {
            private static RandomNumberGenerator _random = new RNGCryptoServiceProvider();

            public static string Generate(int strengthInBits)
            {
                const int bitsPerByte = 8;

                if (strengthInBits % bitsPerByte != 0)
                {
                    throw new ArgumentException("strengthInBits must be evenly divisible by 8.", "strengthInBits");
                }

                int strengthInBytes = strengthInBits / bitsPerByte;

                byte[] data = new byte[strengthInBytes];
                _random.GetBytes(data);
                return HttpServerUtility.UrlTokenEncode(data);
            }
        }
    }

}